#!/usr/bin/python
#coding=utf8

import re, time, logging
from utils import generate_timestamp_13bit, generate_headers, test_connect
from utils import print_terminal_qrcode, save_http_file, show_image

class WXLogin:
    logging.basicConfig(level=logging.INFO)
    _logger = logging.getLogger('login')
    ROOT_URL = 'https://wx.qq.com/'
    LOGIN_URL = 'https://login.weixin.qq.com'
    uuid = ''


    def __init__(self, session) -> None:
        super().__init__()
        self._session = session


    def login(self):
        if not test_connect("https://login.weixin.qq.com"):
            self._logger.error("网络连接失败.")
            return
        while True:
            self.get_login_qrcode_uuid()
            self.show_login_qrcode()
            self._logger.info('请扫描二维码.')
            while True:
                res = self.check_login()
                code = res['code']
                if '400' == code:
                    # 需要重新获得验证码
                    break
                elif '200' == code:
                    return res['redirect_uri']


    """
    检查uuid是否为空
    :param uuid: uuid
    :return: 如果不为空, 返回uuid, 否则返回None
    """
    def check_uuid(self, uuid):
        uuid = uuid or self.uuid
        self.uuid = uuid
        if (uuid == None or 0 == len(uuid)):
            return None
        return uuid


    """
    获得登录二维码的uuid
    :return: 登录二维码的uuid
    """
    def get_login_qrcode_uuid(self) -> str:
        url = '%s/jslogin?' % self.LOGIN_URL
        params = 'appid=%s&redirect_uri=%s&fun=%s&lang=%s&_=%s' % (
            'wx782c26e4c19acffb',
            'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage',
            'new',
            'zh_CN',
            generate_timestamp_13bit()
        )
        try:
            r = self._session.get(url=url, params=params, headers=generate_headers(self.ROOT_URL, self.LOGIN_URL))
            regx = r'window.QRLogin.code = (\d+); window.QRLogin.uuid = "(\S+?)";'
            data = re.search(regx, r.text)
            if data and data.group(1) == '200':
                uuid = data.group(2)
                self._logger.debug("成功获得登录二维码的uuid [%s]" % uuid)
                self.uuid = uuid
                return uuid
            else:
                self._logger.error("未返回登录二维码的uuid. response: " + r.text)
        except:
            self._logger.error("请求获得登录二维码的uuid失败")


    """
    显示登录二维码
    :param uuid: 二维码的uuid
    """
    def show_login_qrcode(self, uuid:str = None, show_terminal:bool = True):
        if None == self.check_uuid(uuid):
            self._logger.error("不能显示二维码, 因为二维码的uuid为空.")
            return
        if show_terminal:
            # 这里需要注意
            # QRCode('https://login.weixin.qq.com/l/' + uuid) 的意思是
            # 生成内容为 'https://login.weixin.qq.com/l/' + uuid 的二维码, 而不是打开网页的二维码
            print_terminal_qrcode(self.LOGIN_URL + '/l/' + self.uuid)
        else:
            # 显示网页 'https://login.weixin.qq.com/qrcode/' + uuid 的图片
            filePath = 'login_qrcode.jpg'
            save_http_file(self.LOGIN_URL + '/qrcode/' + uuid, filePath)
            show_image(filePath)


    """
    检查是否登录
    :param uuid: 二维码的uuid
    :return: {'code':'返回码', 'userAvatar':'头像信息', 'redirect_uri':'登录信息'}
    返回码:
        200: 登录成功
        201: 已扫描
        400: 二维码失效
        408: 未扫描
    """


    def check_login(self, uuid:str = None):
        uuid = uuid or self.uuid
        if (uuid == None or 0 == len(uuid)):
            self._logger.error("不能检查是否登录, 因为二维码的uuid为空.")
            return {'code':'400'}
        self.uuid = uuid
        self._logger.debug('准备检查uuid [%s] 是否登录.' % uuid)
        url = '%s/cgi-bin/mmwebwx-bin/login?' % self.LOGIN_URL
        localTime = generate_timestamp_13bit()
        params = 'loginicon=%s&uuid=%s&tip=%s&r=%s&_=%s' % (
            'true',
            uuid,
            '0',
            localTime / 1579,
            localTime
        )
        try:
            r = self._session.get(url=url, params=params, headers=generate_headers(self.ROOT_URL, self.LOGIN_URL))
            regx = r'window.code=(\d+)'
            data = re.search(regx, r.text)
            if data and data.group(1) == '200':
                self._logger.info('已获得授权, 准备登录微信.')
                return {'code':'200', 'redirect_uri':re.search(r'window.redirect_uri="(\S+)";', r.text).group(1)}
            elif data and data.group(1) == '201':
                self._logger.info('已扫描二维码 [%s], 请允许登录.' % uuid)
                return {'code':'201', 'userAvatar':re.search(r'window.userAvatar = \'(\S+)\';', r.text).group(1)}
            elif data and data.group(1) == '400':
                self._logger.info('二维码 [%s]已失效, 请重新获得二维码.' % uuid)
                return {'code':'400'}
            elif data:
                return {'code':data.group(1)}
        except:
            self._logger.error("验证二维码 [%s] 登录状态失败." % uuid)
            return {'code':'408'}

